/////////////////////////////////////////////
// ObjectARX defined commands

#include "StdAfx.h"
#include "StdArx.h"
#include "GeAssign.h"

// This is command 'INSRTBLK'
void insrtBlk()
{
	char blkName[50];
	AcDbDatabase *pCurDb;
	AcDbBlockTable *pBlkTable;
	AcDbBlockTableRecord *pBlkTableRecord;
	AcDbBlockTableRecord *pBlkDefRecord;
	AcDbBlockReference *pInsrtObj;
	AcDbEntity *pEnt;
	AcDbBlockTableRecordIterator *pIterator;
	AcDbAttributeDefinition *pAttDef;
	AcDbAttribute *pAtt;
	AcDbObjectId blkId;
	AcDbObjectId insrtId;

	char *pTagPrompt;

	AcGePoint3d insPt;
	AcGePoint3d basePt;

	int retCode;

	retCode = acedGetString(0, "\nEnter Block Name: ", blkName);
	if(retCode != RTNORM || blkName[0] == '\0')
	{
		acutPrintf("\nInvalid block name.");
		return;
	}

	pCurDb = acdbHostApplicationServices()->workingDatabase();

	// Check to see if the block table
	// has blkName

	pCurDb->getBlockTable(pBlkTable, AcDb::kForRead);
	if(!pBlkTable->has(blkName))
	{
		acutPrintf("\nBlock definition %s not found. ", blkName);
		pBlkTable->close();
		return;
	}

	// Get the AcDbObjectId of the block
	// definition.
	pBlkTable->getAt(blkName, blkId);

	pBlkTable->getAt(ACDB_MODEL_SPACE, pBlkTableRecord, AcDb::kForWrite);
	pBlkTable->close();
	
	acedInitGet(RSG_NONULL, NULL);
	acedGetPoint(NULL, "\nPick insertion point: ", asDblArray(insPt));

	pInsrtObj = new AcDbBlockReference(insPt, blkId);

	// Here is where you can set scale, rotation and other
	// properties to the block entity. If you want to
	// see the AcDbBlockReference class for more details.
	pBlkTableRecord->appendAcDbEntity(insrtId, pInsrtObj);


	acdbOpenObject(pBlkDefRecord, blkId, AcDb::kForRead);
	// Now check to see if the Block Definition
	// has attributes. If it does we will add
	// a Block Table Record Iterator to step through
	// the entities and find the Attribute Definitions.

	if(pBlkDefRecord->hasAttributeDefinitions())
	{
		pBlkDefRecord->newIterator(pIterator);

		for(pIterator->start(); !pIterator->done(); pIterator->step())
		{
			pIterator->getEntity(pEnt, AcDb::kForRead);
			// Check to see if the entity is an
			// attribute definition.
			pAttDef = AcDbAttributeDefinition::cast(pEnt);
			if(pAttDef != NULL && !pAttDef->isConstant())
			{
				// If it is and its not constant
				// create a new attribute
				pAtt = new AcDbAttribute();
				// setPropertiesFrom will copy
				// Color, Layer, Linetype,Linetype scale and
				// Visibility.
				pAtt->setPropertiesFrom(pAttDef);
				// setup more properties from the attribute
				// definition
				pAtt->setInvisible(pAttDef->isInvisible());
				basePt = pAttDef->position();
				basePt += pInsrtObj->position().asVector();
				pAtt->setPosition(basePt);
				pAtt->setHeight(pAttDef->height());
				pAtt->setRotation(pAttDef->rotation());

				// Take note how we get the tag.
				pTagPrompt = pAttDef->tag();
				pAtt->setTag(pTagPrompt);
				free(pTagPrompt);

				// Normally you would prompt the user
				// and ask for input values.
				pTagPrompt = pAttDef->prompt();
				acutPrintf("%s%s", "\n", pTagPrompt);
				free(pTagPrompt);
			
				// The setFieldLength is not required
				// even though it is listed in the
				// documentation.
				pAtt->setFieldLength(25);
				// setTextString is the value the
				// attribute receives which would
				// normally be a user input value.
				pAtt->setTextString("This is a test");

				pInsrtObj->appendAttribute(pAtt);
				pAtt->close();
			}
			pEnt->close();
		}// for
	}// if has attribute definitions

	delete pIterator;


	// Note that we close the Model Space
	// block table record after we have added
	// our attributes.
	pBlkTableRecord->close();
	pInsrtObj->close();
}

